package net.oschina.app.util;

import android.content.Context;
import android.os.Environment;
import android.support.v4.util.LruCache;

import com.jakewharton.disklrucache.DiskLruCache;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;

/**
 * Created by YL on 2017/3/25.
 */

public class CacheUtils {
    public final static int MEMORY_CACHE_SIZE = 1024 * 1024 * 5;
    public final static int DISK_MAX_SIZE = 1024 * 1024 * 10;
    public final static String UNIQUENAME = "oschina";
    public final static long DURATION_TIME = 1000 * 60 * 3;// 缓存时间3分钟
    private LruCache<String, String> mLruCache;
    private DiskLruCache mDiskCache;
    private OutputStream mOs;

    public CacheUtils() {
        mLruCache = new LruCache<String, String>(MEMORY_CACHE_SIZE) {
            @Override
            protected int sizeOf(String key, String value) {
                return value.getBytes().length;
            }
        };
        // 2 创建磁盘的DiskLruCache
        //File directory, int appVersion, int valueCount, long maxSize
        File cacheDir = getDiskCacheDir(UIUtils.getContext(), UNIQUENAME);
        int appVersion = PackageUtlis.getVersionCode(UIUtils.getContext());
        //第三个参数指定同一个key可以对应多少个缓存文件，基本都是传1
        int valueCount = 1;
        try

        {
            mDiskCache = DiskLruCache.open(cacheDir, appVersion, valueCount, DISK_MAX_SIZE);
        } catch (
                IOException e
                )

        {
            e.printStackTrace();
        }

    }

    private File getDiskCacheDir(Context context, String uniquename) {
        String cachePath;
        //通过此方法我们可以知道手机上的存储卡是手机自带的还是外边可插拔的SD卡
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) || !Environment.isExternalStorageRemovable()) {
            cachePath = context.getExternalCacheDir().getPath();
        } else {
            cachePath = context.getCacheDir().getPath();
        }
        return new File(cachePath);
    }

    //获取缓存数据
    private String getMemoryCache(String key) {
        return mLruCache.get(key);
    }

    //存储内存缓存数据
    private void cacheToMemory(String key, String value) {
        mLruCache.put(key, value);
        TLog.log("缓存到内存");
    }

    //获取磁盘的缓存数据
    private String getLocal(String key) {
        // 1 获取SnapShot
        BufferedReader br = null;
        InputStream is;
        try {
            DiskLruCache.Snapshot snapshot = mDiskCache.get(key);
            if (snapshot != null) {
                DiskLruCache.Editor edit = snapshot.edit();
                if (edit != null) {
                    is =  edit.newInputStream(0);
                    //存储到内存中
                    br = new BufferedReader(new InputStreamReader(is));
                    StringBuilder sb = new StringBuilder();
                    String temp;
                    while ((temp = br.readLine()) != null) {
                        sb.append(temp);
                    }
                    edit.commit();
                    System.out.println("硬盘数据");
                    return sb.toString();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            IOUtils.close(br);
        }
        return null;
    }


    //存储磁盘缓存数据
    private void cacheToLocal(String key, String value) {
        BufferedWriter bw = null;
        try {
            if(mDiskCache!=null){
                DiskLruCache.Editor edit = mDiskCache.edit(key);
                if (edit != null) {
                    OutputStream os = edit.newOutputStream(0);
                    bw = new BufferedWriter(new PrintWriter(os));
                    bw.write(value);
                    bw.flush();
                    edit.commit();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IOUtils.close(mOs);
        }
    }

    //通用流程的加载
    public String getCache(String key) {
        //先从内存获取，获取不到到磁盘获取，获取不到返回null网络获取
        String cache = getMemoryCache(key);
        if (cache != null) {
            TLog.log("从内存中获取到");
            return cache;
        }
        //如果获取不到再去磁盘获取
        cache = getLocal(key);
        if (cache != null) {
            TLog.log("从磁盘中获取到");
            return cache;
        }
        TLog.log("从网络中获取到");
        return null;
    }
//将数据存储到缓存
    public void savecache(String key, String value) {
        cacheToMemory(key, value);
        cacheToLocal(key, value);
    }
}
